home *** CD-ROM | disk | FTP | other *** search
/ boe.pres.k12.wv.us / boe.pres.k12.wv.us.zip / boe.pres.k12.wv.us / Utilities / Xerox Workcentre 5335 / Windows Scan / 32-bit_x86 / Francais / cpsimage.cab / data / xipProcs / xipaffine.proc < prev    next >
Text File  |  2009-03-16  |  8KB  |  244 lines

  1. // ELF procedure to apply affine transform to XIPIMAGE. The affine transform
  2. // coefficients should come in on the attribute list for the image and/or image
  3. // layers.
  4.  
  5. #load "xipProcs/printLayer.proc";       // procedural support for image info
  6. #load "xipProcs/printImageLayers.proc";
  7. #load "sys/lang.elf";                   // language support for REFLECTION
  8. #load "sys/transform2d.elf";            // procedural support for transforms
  9.  
  10.  
  11. /*
  12.   Checks if environment supports affine transformation
  13. */
  14. private
  15. PROCEDURE __affineIsValid ()
  16.   RETURNS (BOOLEAN valid)
  17. {
  18.     // Assume environment is good
  19.     valid = TRUE;
  20.  
  21.     // Test the environment for required methods
  22.     try {
  23.         CLASSREF xiref  = REFLECTION.findClass (name: "XIPIMAGE");
  24.         BOOLEAN  isLoad = xiref.hasMethod (name: "affine2d");
  25.         STRING   errmsg;
  26.         if (!isLoad)
  27.         {
  28.             errmsg = "Affine: Cannot find affine2d method on XIPIMAGE class. Use LoadClasses";
  29.             print errmsg;
  30.             SetStatus (op: "continue", msg: errmsg);
  31.             valid = FALSE;
  32.             return;
  33.         }
  34.     }
  35.     catch {
  36.         errmsg = "Affine: Exception during use of REFLECTION. Make sure sys/lang.elf is loaded";
  37.         print errmsg;
  38.         SetStatus (op: "continue", msg: errmsg);
  39.         valid = FALSE;
  40.         return;
  41.     }
  42. }
  43.  
  44. /*
  45.   Retrieves affine transform from first layer of a XIPIMAGE and returns a
  46.   TRANSFORM2D object representing the transformation matrix. If the layer does
  47.   not have a transform, the identity transformation matrix is returned.
  48. */
  49. private
  50. PROCEDURE __getMatrixTransform (XIPIMAGE img)
  51.   RETURNS (TRANSFORM2D matrix)
  52. {
  53.     LIST coeffs = img.getAttr (name: "_DIOMatrixTransform", num: 0);
  54.     if (coeffs)
  55.     {
  56.         // Set coefficients in transformation matrix
  57.         matrix.setCoeffs (coeffs: coeffs);
  58.     }
  59. }
  60.  
  61. /*
  62.   Applies affine transformation to specified layer of a XIPIMAGE
  63. */
  64. private
  65. PROCEDURE __affineLayer (XIPIMAGE img, INTEGER num, TRANSFORM2D base)
  66.   RETURNS (XIPIMAGE imgL)
  67. {
  68.     // Get specified layer from image
  69.     imgL = img.getLayer (num: num);
  70.     if (!imgL)
  71.     {
  72.         SetStatus (op: "continue",
  73.             msg: "Affine: Cannot get image layer " + num);
  74.         return;
  75.     }
  76.  
  77.     // Return copy of image layer if it is not a raster layer (no-op)
  78.     INTEGER layerType = imgL.getMember (member: "layerType");
  79.     if (!IsRasterLayer (layerType: layerType))
  80.     {
  81.         imgL = imgL.Copy ();
  82.         return;
  83.     }
  84.  
  85.     // Get transformation matrix from layer and preconcatenate base transform
  86.     // onto it
  87.     TRANSFORM2D matrix = __getMatrixTransform (img: imgL);
  88.     matrix.concatenate (other: base);
  89.  
  90.     // Prepare matrix coefficients for affine2d (Remove translation)
  91.     LIST coeffs = matrix.getCoeffs ();
  92.     coeffs[4] = 0.0;
  93.     coeffs[5] = 0.0;
  94.     matrix.setCoeffs (coeffs: coeffs);
  95.  
  96.     // Return copy of image layer if resulting matrix is an identity (no-op)
  97.     if (matrix.isIdentity ())
  98.     {
  99.         imgL = imgL.Copy ();
  100.         imgL.clearAttr (name: "_DIOMatrixTransform", num: 0);
  101.         return;
  102.     }
  103.  
  104.     // Get output layer viewport
  105.     DOUBLE xpos      = imgL.getMember (member: "xpos");
  106.     DOUBLE ypos      = imgL.getMember (member: "ypos");
  107.     DOUBLE width     = imgL.getMember (member: "width");
  108.     DOUBLE height    = imgL.getMember (member: "height");
  109.     LIST viewportOut = (xpos, ypos, width, height);
  110.  
  111.     // Apply base transform to output viewport
  112.     viewportOut = base.applyToWin (window: viewportOut);
  113.  
  114.     // Get photometry and bit depth of layer
  115.     INTEGER photometry = imgL.getMember (member: "photometry");
  116.     INTEGER bits       = imgL.getMember (member: "bits");
  117.  
  118.     // Make sure bit depth is valid for affine. If bit depth is not 8, convert
  119.     // to valid bit depth and save original value to restore bit depth after
  120.     // affine transformation.
  121.     BOOLEAN restoreBits = FALSE;
  122.     if (bits != 8)
  123.     {
  124.         imgL = imgL.convert (to: 8);
  125.         restoreBits = TRUE;
  126.     }
  127.  
  128.     // Remove translation coefficients
  129.     coeffs = (coeffs[0], coeffs[1], coeffs[2], coeffs[3]);
  130.  
  131.     // Execute affine transformation
  132.     imgL = imgL.interleave (scanline: 1
  133.                ).affine2d (coeffs: coeffs
  134.                );
  135.  
  136.     // Restore bit depth if necessary
  137.     if (restoreBits)
  138.         imgL = imgL.convert (to: bits);
  139.  
  140.     // Set transformed viewport for layer
  141.     imgL.setMember (member: "xpos",   value: viewportOut[0]);
  142.     imgL.setMember (member: "ypos",   value: viewportOut[1]);
  143.     imgL.setMember (member: "width",  value: viewportOut[2]);
  144.     imgL.setMember (member: "height", value: viewportOut[3]);
  145.  
  146.     // Set image dimensions
  147.     imgL.imageWidth  = viewportOut[2];
  148.     imgL.imageHeight = viewportOut[3];
  149.  
  150.     // Remove transform from layer attributes
  151.     imgL.clearAttr (name: "_DIOMatrixTransform", num: 0);
  152. }
  153.  
  154. /* @Affine
  155.   // DESCRIPTION
  156.   Applies affine transformation to a XIPIMAGE
  157.    
  158.   This procedure applies an affine transformation to a XIPIMAGE, and returns a
  159.   new XIPIMAGE representing the transformed input image.
  160.    
  161.   The matrix argument specifies an optional affine transform to apply to the
  162.   input image. This transform will be applied to each layer of the input image.
  163.   If a layer has another transform attached to it, this transform is
  164.   concatenated to that transform and the resulting transform is then applied
  165.   to the layer. A transform attached to a layer will be removed after the layer
  166.   is transformed.
  167.    
  168.   REQUIREMENTS:
  169.   Requires the system lang classes
  170.         #load "sys/lang.elf";
  171.   Requires the image processing classes from the xeng library
  172.         LoadClasses (filename: "xeng");
  173. */
  174. PROCEDURE Affine (XIPIMAGE imgIn, TRANSFORM2D matrix)
  175.   RETURNS (XIPIMAGE imgOut)
  176. {
  177.     // Check for valid XIPIMAGE
  178.     if (!imgIn)
  179.     {
  180.         STRING errmsg = "Affine: Source image is not valid";
  181.         print errmsg;
  182.         SetStatus (op: "continue", msg: errmsg);
  183.         return;
  184.     }
  185.  
  186.     // Check if environment supports affine transformation
  187.     if (!__affineIsValid ())
  188.         return;
  189.  
  190.     // Determine resolution of input image
  191.     DOUBLE xres = imgIn.resolution[0];
  192.     DOUBLE yres = imgIn.resolution[1];
  193.  
  194.     if (xres <= 0.0)
  195.     {
  196.         xres = 300.0;
  197.         yres = 300.0;
  198.     }
  199.     else if (yres <= 0.0)
  200.         yres = xres;
  201.  
  202.     // Set dimensions and resolution of output image
  203.     imgOut.imageWidth  = imgIn.imageWidth;
  204.     imgOut.imageHeight = imgIn.imageHeight;
  205.     imgOut.resolution  = (xres, yres);
  206.  
  207.     LIST window = (0.0, 0.0, imgOut.imageWidth, imgOut.imageHeight);
  208.  
  209.     // Preconcatenate page rotation to input matrix if necessary
  210.     INTEGER angle = imgIn.getAttr (name:"_PDFrotate");
  211.     if (angle != 0) {
  212.         TRANSFORM2D rotmatrix;
  213.         rotmatrix.rotate (angle: angle);
  214.         LIST tmpwin = rotmatrix.applyToWin (window: window);
  215.         rotmatrix.translate (tx: -tmpwin[0], ty: -tmpwin[1]);
  216.         matrix.preconcatenate (other: rotmatrix);
  217.     }
  218.  
  219.     // Apply input matrix to output image
  220.     window             = matrix.applyToWin (window: window);
  221.     imgOut.imageWidth  = window[2];
  222.     imgOut.imageHeight = window[3];
  223.  
  224.     // Make sure image is uncompressed
  225.     imgIn = imgIn.unCompress ();
  226.  
  227.     // Apply affine transformation to each layer of input image
  228.     XIPIMAGE imgL;
  229.     INTEGER  i;
  230.     for (i = 0; i < imgIn.nlayers; i++)
  231.     {
  232.         imgL = __affineLayer (img: imgIn, num: i, base: matrix);
  233.  
  234.         imgOut.addLayer (image: imgL);
  235.     }
  236.  
  237.     LIST attrs = imgIn.getAttr ();
  238.     for (i = 0; i < attrs.length (); i++)
  239.         imgOut.setAttr (name: attrs.name (entry: i), obj: attrs[i]);
  240.  
  241.     // Now remove the _PDFRotate because it was applied in pre-concatenate
  242.     imgOut.clearAttr(name:"_PDFrotate");
  243. }
  244.